home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
source
/
vr386
/
objrend.asm
< prev
next >
Wrap
Assembly Source File
|
1993-12-27
|
11KB
|
544 lines
TITLE OBJREND - RENDERER SUPPORT MATH IN ASSEMBLER
COMMENT $
// 26/12/93 by Dave Stampe
// All algorithms and code (c) 1993 by Dave Stampe
/*
This code is part of the REND386 project, created by Dave Stampe and
Bernie Roehl.
Copyright 1992, 1993, 1994 by Dave Stampe and Bernie Roehl.
May be freely used to write software for release into the public domain;
all commercial endeavours MUST contact BOTH Bernie Roehl and Dave Stampe
for permission to incorporate any part of this software into their
products! Usually there is no charge for under 50-100 items for
low-cost or shareware, and terms are reasonable. Any royalties are used
for development, so equipment is often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to REND386, Dave Stampe,
and Bernie Roehl in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling! No more
code ripoffs please.
CONTACTS: dstampe@psych.toronto.edu, broehl@sunee.uwaterloo.ca
See the COPYRITE.H file for more information.
*/
This file has object and poly depth-sorting code and object
bounding sphere view-volume clipping routines. It also computes
the screen extent of the object bounding sphere (roughly) and
preclears object flags for rendering.
Both quicksort and insertion sort are supplied, to optimally
support poly counts from 2 to 2000.
/* Contact: dstampe@sunee.waterloo.edu */
$
.MODEL large
.386
.DATA
include 3dstruct.inc
include viewdata.inc
.CODE RENDERER
;/********* QUICKSORT OF OBJECT OR POLYS BY DEPTH *******/
; uses near ptrs for speed
; sorta in descending order
;/* m, n actually near ptrs into array */
;/* es is seg. of array throughout */
;/* keep array under 64K in size! */
;static void qsort_iter(int m, int n)
; NEAR for speed
m equ [bp+6]
n equ [bp+4]
qsort_iter PROC NEAR
push bp
mov bp,sp
mov si,m ; end of sort tree?
cmp si,n
jge end_of_sort
mov di,n ; setup for pass
add di,8
mov eax,DWORD PTR es:[si].DS_depth
gloop:
fmax: ; find one less than current
add si,8
cmp DWORD PTR es:[si].DS_depth,eax
jg fmax
fmin: ; find one grater than current
sub di,8
cmp DWORD PTR es:[di].DS_depth,eax
jl fmin
cmp si,di ; swap or subdivide?
jge nonswap
mov ebx,DWORD PTR es:[si] ; just swap entries, try next
mov edx,DWORD PTR es:[di]
mov DWORD PTR es:[di],ebx
mov DWORD PTR es:[si],edx
mov ebx,DWORD PTR es:[si+4]
mov edx,DWORD PTR es:[di+4]
mov DWORD PTR es:[di+4],ebx
mov DWORD PTR es:[si+4],edx
jmp gloop
nonswap: ; swap and subdivide
mov si,m
mov ebx,DWORD PTR es:[si]
mov edx,DWORD PTR es:[di]
mov DWORD PTR es:[di],ebx
mov DWORD PTR es:[si],edx
mov ebx,DWORD PTR es:[si+4]
mov edx,DWORD PTR es:[di+4]
mov DWORD PTR es:[di+4],ebx
mov DWORD PTR es:[si+4],edx
sub di,8 ; pivot - 1
cmp si,di
jge skip_qs1
push si ; m argument
push di ; n argument
call near ptr qsort_iter
pop di
pop si
skip_qs1:
add di,16 ; pivot + 1
cmp di,WORD PTR n
jge end_of_sort
push di ; m argument
push WORD PTR n ; n argument
call near ptr qsort_iter
add sp,4
end_of_sort:
pop bp
retn
qsort_iter endp
; quicksort of poly/object array
;
; void qsort_dsort(DSORT far *first, DSORT far *last);
first equ [bp+8] ; arguments
last equ [bp+12]
PUBLIC _qsort_dsort
_qsort_dsort proc far
.386
push ebp
mov ebp,esp
push edx
push ecx
push esi
push edi
mov ax,WORD PTR first+2 ; args must be in same segment
cmp ax,WORD PTR last+2
jne no_sort
les di,DWORD PTR first ; sanity check
mov si,WORD PTR last
cmp di,si
jae no_sort
push di ; start sort
push si
call near ptr qsort_iter
add esp,4
no_sort:
pop edi
pop esi
pop ecx
pop edx
mov esp,ebp
pop ebp
ret
_qsort_dsort endp
;/********* FAST SORT OF OBJECT OR POLYS BY DEPTH *******/
; insertion sort of poly/object array
; faster than quicksort if less than 16 items
; sorts in descending order
;
; void insertion_dsort(DSORT far *first, DSORT far *last);
first equ DWORD PTR [bp+8] ; arguments
last equ DWORD PTR [bp+12]
PUBLIC _insertion_dsort
_insertion_dsort proc far
push ebp ; di is start/current pivot
mov ebp,esp ; si is end marker
; bx is search pointer
push edx ; eax is comparison
push esi
push edi
mov ax,WORD PTR first+2 ; args must be in same segment
cmp ax,WORD PTR last+2
jne no_sort
les di,DWORD PTR first
mov si,WORD PTR last
outer_loop: ; sanity/finished check
cmp di,si
jae end_sort
mov bx,di ; search ptr
mov eax,080000001h ; comparison value : init to big_neg
mov dx,bx ; records biggest found
find_loop:
cmp eax,es:[bx].DS_depth ; biggest so far?
jge dont_swap
mov eax,es:[bx].DS_depth ; record
mov dx,bx
dont_swap:
add bx,8 ; size DSORT ; next item
cmp bx,si ; past last?
jbe find_loop
cmp dx,di ; no swap needed?
je no_swap_req
mov bx,dx
mov eax,DWORD PTR es:[di] ; swap current with smallest
mov edx,DWORD PTR es:[bx]
mov DWORD PTR es:[bx],eax
mov DWORD PTR es:[di],edx
mov eax,DWORD PTR es:[bx+4]
mov edx,DWORD PTR es:[di+4]
mov DWORD PTR es:[di+4],eax
mov DWORD PTR es:[bx+4],edx
no_swap_req:
add di,8 ; size DSORT
jmp outer_loop
end_sort:
pop edi ; finished!
pop esi
pop edx
mov esp,ebp
pop ebp
ret
_insertion_dsort endp
;/************ OBJECT-CLIPPING BY VIEW VOLUME **************/
;#define OUT_OF_VIEW 0x8000000L // returned if we can't see object
;long obj_clip_by_volume(OBJECT *obj)
obj equ DWORD PTR [bp+8] ; arguments
center_z equ DWORD PTR [bp-4] ; locals
center_z4 equ DWORD PTR [bp-8]
tx equ DWORD PTR es:[bx].O_sphx ; bounding sphere center
ty equ DWORD PTR es:[bx].O_sphy
tz equ DWORD PTR es:[bx].O_sphz
r equ DWORD PTR es:[bx].O_sphr ; bounding sphere radius
PUBLIC _obj_clip_by_volume
_obj_clip_by_volume proc far
.386
push ebp
mov ebp,esp
sub esp,12
push esi
push edi
push ecx
les bx,obj
mov eax,_VS_fact7 ; convert center Z to camera coords
mov edx,tx
sub edx,_VS_iview_x
imul edx
mov esi,eax
mov edi,edx
mov eax,_VS_fact8
mov edx,ty
sub edx,_VS_iview_y
imul edx
add esi,eax
adc edi,edx
mov eax,_VS_fact9
mov edx,tz
sub edx,_VS_iview_z
imul edx
add esi,eax
adc edi,edx
shrd esi,edi,27 ;29-PRESCALEZ ; shift is prescaled
mov center_z4,esi
sar esi,2 ;PRESCALEZ ; now un-prescaled
mov center_z,esi
add esi,r
cmp esi,_VS_hither
jl outofview ; too close
sub esi,r
sub esi,r
cmp esi,_VS_yon
jg outofview ; too far
mov eax,_VS_fact1 ; convert X coord to camera space
mov edx,tx
sub edx,_VS_iview_x
imul edx
mov esi,eax
mov edi,edx
mov eax,_VS_fact2
mov edx,ty
sub edx,_VS_iview_y
imul edx
add esi,eax
adc edi,edx
mov eax,_VS_fact3
mov edx,tz
sub edx,_VS_iview_z
imul edx
add esi,eax
adc edi,edx
shrd esi,edi,29 ; now camera x coord of center
; DO LEFT PLANE TEST
mov eax,_VS_left_C ; multiply by slope
neg eax
imul center_z
shrd eax,edx,29
mov ecx,eax
sub ecx,r
mov eax,_VS_left_M ; second term
imul esi
shrd eax,edx,29
cmp ecx,eax
jg outofview ; too far left
mov eax,_VS_right_C ; DO RIGHT PLANE TEST
neg eax
imul center_z
shrd eax,edx,29
mov ecx,eax
sub ecx,r
mov eax,_VS_right_M
imul esi
shrd eax,edx,29
neg eax
cmp ecx,eax
jg outofview ; too far right
mov eax,_VS_fact4 ; compute Y coord of center
mov edx,tx
sub edx,_VS_iview_x
imul edx
mov esi,eax
mov edi,edx
mov eax,_VS_fact5
mov edx,ty
sub edx,_VS_iview_y
imul edx
add esi,eax
adc edi,edx
mov eax,_VS_fact6
mov edx,tz
sub edx,_VS_iview_z
imul edx
add esi,eax
adc edi,edx
shrd esi,edi,29 ; y coord in camera space of center
mov eax,_VS_bot_C ; BOTTOM PLANE CLIP
neg eax
imul center_z
shrd eax,edx,29
mov ecx,eax
sub ecx,r
mov eax,_VS_bot_M
imul esi
shrd eax,edx,29
cmp ecx,eax
jg outofview ; too far down
mov eax,_VS_top_C ; TOP PLANE CLIP
neg eax
imul center_z
shrd eax,edx,29
mov ecx,eax
sub ecx,r
mov eax,_VS_top_M
imul esi
shrd eax,edx,29
neg eax
cmp ecx,eax ; too far up
jg outofview
mov eax,center_z4 ; return Z if OK
jmp ret_32
outofview:
mov eax,OUT_OF_VIEW ; flag, none of sphere in view volume
ret_32:
shld edx,eax,16 ; return value in both EAX and DX:AX
pop ecx
pop edi
pop esi
mov esp,ebp
pop ebp
ret
_obj_clip_by_volume endp
;/********* ESTIMATE SCREEN WIDTH FOR REP SELECT ***********/
; only use if object has passed preclip!
; returns -1 if error
;
; long compute_obj_screen_size(OBJECT *obj, long center_z);
obj equ DWORD PTR [bp+8] ; arguments
center_z equ DWORD PTR [bp+12]
r equ DWORD PTR es:[bx].O_sphr ; bounding sphere radius
PUBLIC _compute_obj_screen_size
_compute_obj_screen_size proc far
.386
push ebp
mov ebp,esp
les bx,obj
mov eax,r ; /* size = scale*radius/distance */
imul DWORD PTR _VS_scx
shrd eax,edx,8 ; /* range-extended <16.16> -> <32.0> */
sar edx,8
idiv DWORD PTR center_z
sar eax,6 ; /* 2x true size so it's diameter */
shld edx,eax,16 ; result in eax AND dx:ax
mov esp,ebp
pop ebp
ret
_compute_obj_screen_size endp
;/********* CLEAR OBJECT FLAGS FOR RENDERING ***********/
; a representation must be current!
;
; void prerender_clear_object(OBJECT *obj);
obj equ DWORD PTR [bp+8] ; arguments
PUBLIC _prerender_clear_object
_prerender_clear_object proc far
.386
push ebp
mov ebp,esp
les bx,obj
les bx,es:[bx].O_currep ; current object representation
mov ax,es:[bx].R_nverts
les bx,es:[bx].R_verts
clear_loop:
mov DWORD PTR es:[bx].V_nvptr,0
mov WORD PTR es:[bx].V_zxflag,0 ; clears outcode and flags
add bx,SIZE VERTEX
dec ax
jne clear_loop
mov esp,ebp
pop ebp
ret
_prerender_clear_object endp
end